using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using RAG.Domain.Entities.App;
using RAG.Application.Interfaces;
using System.Collections.Generic;
using System.Linq;

namespace RAG.Application.Services
{
    public class AppTokenService : IAppTokenService
    {
        private readonly string _jwtSecret;
        private readonly string _issuer;
        private readonly string _audience;
        private readonly int _expireMinutes;

        public AppTokenService(IConfiguration configuration)
        {
            try
            {
                // 从配置文件读取JWT设置
                var jwtSettings = configuration.GetSection("Jwt");
                
                if (!jwtSettings.Exists())
                {
                    throw new InvalidOperationException("JWT配置节不存在");
                }
                
                // 读取配置值，使用硬编码默认值确保一致性
                _jwtSecret = jwtSettings["SecretKey"] ?? "RAGApiSecretKeyRAGApiSecretKeyRAGApiSecretKeyRAGApiSecretKeyRAGApiSecretKey";
                _issuer = jwtSettings["Issuer"] ?? "RAGApi";
                _audience = jwtSettings["Audience"] ?? "RAGClient";
                _expireMinutes = int.TryParse(jwtSettings["ExpireMinutes"], out var minutes) ? minutes : 120;
                
                // 验证配置
                if (string.IsNullOrEmpty(_jwtSecret) || string.IsNullOrEmpty(_issuer) || string.IsNullOrEmpty(_audience))
                {
                    throw new InvalidOperationException("JWT配置不完整，请检查appsettings.json中的Jwt配置节");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"AppTokenService: 初始化失败 - {ex.Message}");
                throw;
            }
        }

        public (string AccessToken, string RefreshToken) GenerateTokens(Users user)
        {
            if (user == null)
                throw new ArgumentNullException(nameof(user));

            var accessToken = GenerateAccessToken(user);
            var refreshToken = GenerateRefreshToken(user);
            
            return (accessToken, refreshToken);
        }

        public string GenerateAccessToken(Users user)
        {
            return GenerateToken(user, TimeSpan.FromMinutes(_expireMinutes), "access");
        }

        public string GenerateRefreshToken(Users user)
        {
            return GenerateToken(user, TimeSpan.FromDays(7), "refresh");
        }

        private string GenerateToken(Users user, TimeSpan expires, string tokenType)
        {
            if (user == null)
                throw new ArgumentNullException(nameof(user));

            // 确保 issuer 和 audience 不为空
            var issuer = string.IsNullOrEmpty(_issuer) ? "RAGApi" : _issuer;
            var audience = string.IsNullOrEmpty(_audience) ? "RAGClient" : _audience;

            // 创建签名密钥和凭据
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSecret));
            var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            
            // 创建JWT令牌 - 使用简化的方式
            var now = DateTime.UtcNow;
            var token = new JwtSecurityToken(
                issuer: issuer,
                audience: audience,
                claims: CreateSimpleClaims(user, tokenType),
                notBefore: now,
                expires: now.Add(expires),
                signingCredentials: credentials
            );

            // 生成令牌字符串
            var tokenString = new JwtSecurityTokenHandler().WriteToken(token);
            
            return tokenString;
        }

        /// <summary>
        /// 创建包含权限信息的JWT claims
        /// </summary>
        private IEnumerable<Claim> CreateSimpleClaims(Users user, string tokenType)
        {
            var claims = new List<Claim>();

            // 添加基本claims - 确保值不为空且清理特殊字符
            if (!string.IsNullOrWhiteSpace(user.Id.ToString()))
            {
                claims.Add(new Claim("sub", user.Id.ToString().Trim()));
                claims.Add(new Claim("user_id", user.Id.ToString().Trim()));
                claims.Add(new Claim("uid", user.Id.ToString().Trim()));
            }

            if (!string.IsNullOrWhiteSpace(user.Username))
            {
                var cleanUsername = user.Username.Trim().Replace("\n", "").Replace("\r", "").Replace("\t", "");
                claims.Add(new Claim("name", cleanUsername));
                claims.Add(new Claim("username", cleanUsername));
            }

            if (!string.IsNullOrWhiteSpace(user.Email))
            {
                var cleanEmail = user.Email.Trim().Replace("\n", "").Replace("\r", "").Replace("\t", "");
                claims.Add(new Claim("email", cleanEmail));
            }

            // 添加token类型
            claims.Add(new Claim("token_type", tokenType.Trim()));

            // 添加用户状态信息
            claims.Add(new Claim("account_status", user.AccountStatus.ToString()));
            claims.Add(new Claim("is_active", user.IsActive.ToString()));

            return claims;
        }

        public string? RefreshAccessToken(string refreshToken)
        {
            try
            {
                // 输入验证和清理
                if (string.IsNullOrWhiteSpace(refreshToken))
                {
                    return null;
                }

                // 清理令牌 - 移除所有可能的特殊字符
                refreshToken = refreshToken.Trim()
                    .Replace("\n", "")
                    .Replace("\r", "")
                    .Replace("\t", "")
                    .Replace(" ", "");

                // 验证令牌格式
                if (!refreshToken.StartsWith("eyJ"))
                {
                    return null;
                }
                
                // 检查令牌部分
                var parts = refreshToken.Split('.');
                
                if (parts.Length != 3)
                {
                    return null;
                }

                // 读取令牌
                var handler = new JwtSecurityTokenHandler();
                
                if (!handler.CanReadToken(refreshToken))
                {
                    return null;
                }

                var token = handler.ReadJwtToken(refreshToken);

                // 检查令牌类型
                var tokenType = token.Claims.FirstOrDefault(c => c.Type == "token_type")?.Value;
                if (tokenType != "refresh")
                {
                    return null;
                }

                // 检查令牌是否过期
                if (token.ValidTo < DateTime.UtcNow)
                {
                    return null;
                }

                // 获取用户信息 - 使用多种claim类型查找
                var userId = token.Claims.FirstOrDefault(c => c.Type == "sub")?.Value
                    ?? token.Claims.FirstOrDefault(c => c.Type == "user_id")?.Value
                    ?? token.Claims.FirstOrDefault(c => c.Type == "uid")?.Value;
                    
                var username = token.Claims.FirstOrDefault(c => c.Type == "name")?.Value
                    ?? token.Claims.FirstOrDefault(c => c.Type == "username")?.Value;
                    
                var email = token.Claims.FirstOrDefault(c => c.Type == "email")?.Value;

                if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(username))
                {
                    return null;
                }

                // 创建用户对象并生成新的访问令牌
                var user = new Users
                {
                    Id = Guid.Parse(userId),
                    Username = username,
                    Email = email ?? ""
                };

                var newAccessToken = GenerateAccessToken(user);
                
                return newAccessToken;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"RefreshAccessToken: 刷新失败 - {ex.Message}");
                return null;
            }
        }

        public bool IsAccessTokenExpiringSoon(string accessToken, int minutesBeforeExpiry = 30)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(accessToken))
                    return false;

                // 清理token
                accessToken = CleanToken(accessToken);

                var handler = new JwtSecurityTokenHandler();
                var token = handler.ReadJwtToken(accessToken);
                var timeUntilExpiry = token.ValidTo - DateTime.UtcNow;
                return timeUntilExpiry <= TimeSpan.FromMinutes(minutesBeforeExpiry);
            }
            catch
            {
                return true;
            }
        }

        /// <summary>
        /// 清理token中的特殊字符
        /// </summary>
        private string CleanToken(string token)
        {
            if (string.IsNullOrWhiteSpace(token))
                return token;

            return token.Trim()
                .Replace("\n", "")
                .Replace("\r", "")
                .Replace("\t", "")
                .Replace(" ", "");
        }

        /// <summary>
        /// 验证token格式是否正确
        /// </summary>
        public bool IsValidTokenFormat(string token)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(token))
                    return false;

                // 清理token
                token = CleanToken(token);

                // 检查是否以eyJ开头（JWT标准）
                if (!token.StartsWith("eyJ"))
                    return false;

                // 检查是否包含三个部分（header.payload.signature）
                var parts = token.Split('.');
                if (parts.Length != 3)
                    return false;

                // 尝试解析token
                var handler = new JwtSecurityTokenHandler();
                return handler.CanReadToken(token);
            }
            catch
            {
                return false;
            }
        }
    }
}